<template>
    <div class="upload-wrap">
        <a-upload-dragger name="file" v-bind="$attrs" :showUploadList="false" :customRequest="handleUpdoadingFile" :beforeUpload="handleBeforeUpload">
            <flexbox justify="center" align="center">
                <p class="ant-upload-drag-icon"><InboxOutlined /></p>
                <span>添加文档或<a style="text-decoration: underline">浏览</a></span>
            </flexbox>
            <p class="ant-upload-text">仅支持：.xlsx</p>
        </a-upload-dragger>
        <div class="file-list-cont">
            <assets-file v-bind="$attrs" :fileList="showFileList" />
        </div>
    </div>
</template>

<script lang="ts">
import AssetsFile from '@/components/AssetsFile/AssetsFile.vue';
import { message } from 'ant-design-vue';
import { genPercentAdd, fileToObject, getFileItem } from '@/utils/uploadFile';
import { InboxOutlined } from '@ant-design/icons-vue';
import { isNotEmpty } from '@/utils/is';
import { defineComponent, ref, unref, computed } from 'vue';
export default defineComponent({
    name: 'UploadCell',
    components: {
        InboxOutlined,
        AssetsFile
    },
    props: {
        fileList: { type: Array, default: () => [] },
        uploadConfig: { type: Object, default: () => ({}) }
    },
    emits: ['success'],
    setup(props, { emit }) {
        const allFileList = ref<any[]>([]); // 已经存在的文件(详情返回)
        //筛选出没有删除的文件
        const showFileList = computed(() => {
            return unref(allFileList).filter((file: any) => file.status !== 'delete');
        });
        const handleUpdoadingFile = (options: any) => {
            // this.allFileList = [];
            const name = options.file.name.replace(/[?？*<>()（）{}$&:："“”|\\/\\[\]【】]/gi, '');
            const file: any = new File([options.file], name);
            const formData = new FormData();
            formData.append('files', file);
            if (isNotEmpty(props.uploadConfig.query)) {
                Object.keys(props.uploadConfig.query).forEach((key) => {
                    formData.append(key, props.uploadConfig.query[key]);
                });
            }
            // 更新进度条数值
            const autoUpdateProgress = (percent: number, file: any, fileList: any[]) => {
                const targetItem = getFileItem(file, fileList);
                // removed
                if (!targetItem) {
                    return;
                }
                targetItem.percent = percent * 100;
                allFileList.value = fileList.concat(); // 更新列表
            };
            const config = {
                // 增加进度条事件，上传中会不断调用该方法
                onUploadProgress: (progressEvent: any) => {
                    const percent = genPercentAdd()(progressEvent.loaded / progressEvent.total);
                    const targetItem = fileToObject(file);
                    // 当前上传文件
                    targetItem.status = 'uploading';
                    const nextFileList = unref(allFileList).concat();
                    const fileIndex = nextFileList.findIndex((_ref: any) => {
                        const uid = _ref.uid;
                        return uid === targetItem.uid;
                    });
                    if (fileIndex === -1) {
                        nextFileList.push(targetItem);
                    } else {
                        nextFileList[fileIndex] = targetItem; // 保证是同一文件覆盖
                    }
                    autoUpdateProgress(percent, targetItem, nextFileList);
                },
                cancelDuplicated: true //取消重复检测
            };
            props.uploadConfig
                .request(formData, config)
                .then((res) => {
                    // 可能会出现超时
                    if (res.success) {
                        message.success(`${options.file.name}上传成功`);
                        options.onSuccess(res, options.file); //这个会添加response信息字段
                    } else {
                        // 手动添加status，不然超时情况无法捕捉
                        const targetItem = getFileItem(file, unref(allFileList));
                        if (targetItem) {
                            targetItem.status = 'error';
                        }
                        message.error(`${options.file.name}上传失败`);
                    }
                    emit('success', res);
                })
                .catch(() => {
                    options.onError(); //这个会添加response和error信息字段，status会从uploading变为error
                    message.error(`${options.file.name}上传失败`);
                });
        };
        // 上传前检测大小
        const handleBeforeUpload = (file) => {
            const size: number = file.size;
            const max = 60;
            // 不能带有[]符号
            // if (/[*<>(){}$&?:"|\\/\\[\]]/gi.test(file.name)) {
            //     message.error('上传文件名称不能带有特殊符号：<>(){}$&?:|/\\[]');
            //     return false;
            // }
            if (size / 1024 / 1024 > max) {
                message.error('上传文件过大');
                return false;
            }
            const index = file.name.lastIndexOf('.');
            if (index >= 0) {
                const type = file.name.slice(index + 1);
                if (type !== 'xlsx') {
                    message.error('上传文件格式不正确');
                    return false;
                }
            }
            return true;
        };
        return {
            showFileList,
            handleBeforeUpload,
            handleUpdoadingFile
        };
    }
});
</script>

<style lang="less">
// 上传
.upload-wrap {
    margin-top: 8px;
}
.ant-upload.ant-upload-drag {
    .ant-upload-text {
        color: #8e94a1 !important;
        font-size: 12px !important;
    }
    p.ant-upload-drag-icon {
        margin-bottom: -4px !important;
        margin-right: 8px;
        .anticon {
            font-size: 18px;
            color: #000;
        }
    }
}
.file-list-cont {
    margin-top: 8px;
}
</style>
